#include "oj_control.hpp"

using namespace ns_util;
using namespace ns_control;

void manual(const std::string argv)
{
    std::cout << "Use Error,please Use:" << "\n";
    std::cout << "\t" << argv << " port" << "\n";
}
std::string GetSessionId(const Request &req)
{
    std::vector<std::string> v;
    StrUtil::SplitString(v, req.get_header_value("Cookie"), "=");
    std::string sessionId;
    if (v.size() > 1)
        return sessionId = v[1];
    return std::string();
}
int main(int args,char* argv[])
{
    if(args != 2)
    {
        manual(argv[0]);
        exit(1);
    }
    httplib::Server svr;
    Control cl;
    srand(time(nullptr));

    // 获取所有的题目
    svr.Get("/all_questions", [&cl](const Request &req, Response &resp)
            {
        LOG(INFO) << "有题库请求出现ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
        std::string outhtml;
        //获取sessionId
        std::string sessionId = GetSessionId(req);

        if(!cl.AllQuestions(&outhtml,sessionId))
        {
            //应该返回5xx系列
            std::string html_500;
            FileUtil::ReadFile(html_500,"wwwroot/500.html");
            resp.set_content(html_500,"text/html; charset=utf-8");
            return;
        }
        resp.set_content(outhtml,"text/html; charset=utf-8"); });

    // 获取一个题目
    // 使用正则表达式/question/1
    // R"()",原始字符串raw string,保持字符串原貌，不做特殊转义
    svr.Get(R"(/question/(\d+))", [&cl](const Request &req, Response &resp)
            {
        LOG(INFO) << "有单题请求出现ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
        std::string outhtml;
        //获取到题号，matches[0]获取GET的路径全称(/question/number)
        std::string number = req.matches[1];
        //获取sessionId
        std::string sessionId = GetSessionId(req);

        if(!cl.OneQuestion(&outhtml,number,sessionId))
        {
            //应该返回5xx系列
            std::string html_500;
            FileUtil::ReadFile(html_500,"wwwroot/500.html");
            resp.set_content(html_500,"text/html; charset=utf-8");
            return;
        }
        resp.set_content(outhtml,"text/html; charset=utf-8"); });

    // 判题服务
    svr.Post(R"(/judge/(\d+))", [&cl](const Request &req, Response &resp)
             {
        LOG(INFO) << "有编译请求出现ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
        std::string out_json;
        std::string number = req.matches[1];
        std::string in_json = req.body;
        //获取sessionId
        std::string sessionId = GetSessionId(req);
        //返回值小于零都是有问题的
        int code = cl.ParseQuestion(number,in_json,&out_json,sessionId);
        if(code < 0)
        {
            Json::Value outValue;
            outValue["comp_server_code"] = code;
            std::vector<std::string> err = {"服务器走神了。。。","服务器睡着了","休息一会吧"};
            switch (code){
                case -1:
                    //可能编译服务全挂了
                    LOG(FAIL) << "用户无法使用编译服务" << "\n";
                    outValue["comp_server_err"] = err[rand()%3];
                    break;
                case -2:
                    outValue["comp_server_err"] = "请登录，您未登录或登录已过期";
                    break;
                case -3:
                    outValue["comp_server_err"] = "外星人入侵";
                    break;
                default:
                    break;
            }

            Json::StyledWriter write;
            out_json = write.write(outValue);
            resp.set_content(out_json,"application/json; charset=utf-8");        
            return;
        }
        resp.set_content(out_json,"application/json; charset=utf-8"); });
    // 登录页面
    svr.Get("/loginhtml", [](const Request &req, Response &resp)
            {
        std::string login_html;
        FileUtil::ReadFile(login_html,"wwwroot/login.html");
        resp.set_content(login_html,"text/html; charset=utf-8"); });
    // 登录
    svr.Post("/login", [&cl](const Request &req, Response &resp)
             {
                LOG(INFO) << "有登录请求出现,ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
                std::string in_json = req.body;
                std::string out_json;
                if(!cl.UsrLogin(in_json,&out_json))
                {
                    //函数调用失败
                    LOG(ERROR) << "未知错误" << "\n";
                }
                resp.set_content(out_json,"application/json; charset=utf-8"); });

    // 注册
    svr.Post("/register", [&cl](const Request &req, Response &resp)
             {
                LOG(INFO) << "有注册请求出现,ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
                std::string in_json = req.body;
                std::string out_json;

                if(!cl.UsrRegister(in_json,&out_json))
                {
                    //函数调用失败
                    LOG(ERROR) << "未知错误" << "\n";
                }
                resp.set_content(out_json,"application/json; charset=utf-8"); });

    // 请求聊天页面
    svr.Get("/chat_page", [&cl](const Request &req, Response &resp)
             {
                LOG(INFO) << "聊天页面请求,ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
                std::string outhtml;
                //获取sessionId
                std::string sessionId = GetSessionId(req);
                if(!cl.ChatPage(&outhtml,sessionId))
                {
                    //函数调用失败
                    LOG(ERROR) << "未知错误" << "\n";
                }
                resp.set_content(outhtml,"text/html; charset=utf-8"); });

    // 发送聊天请求
    svr.Post("/char_send", [&cl](const Request &req, Response &resp)
             {
                LOG(INFO) << "有聊天消息发送请求出现,ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
                std::string in_json = req.body;
                std::string out_json;
                if(!cl.ChatSend(in_json,&out_json))
                {
                    //函数调用失败
                    LOG(ERROR) << "可能未登录,未知错误" << "\n";
                }
                resp.set_content(out_json,"application/json; charset=utf-8"); });

    // 接收聊天请求
    svr.Post("/char_recv", [&cl](const Request &req, Response &resp)
             {
                // LOG(INFO) << "有聊天消息接受请求出现,ip:" << req.remote_addr << " 端口:" << req.remote_port << "\n";
                std::string in_json = req.body;
                std::string out_json;
                if(!cl.ChatRecv(in_json,&out_json))
                {
                    //暂时无消息或未登录
                }
                resp.set_content(out_json,"application/json; charset=utf-8"); });

    // 错误路由
    svr.set_error_handler([](const Request &req, Response &resp)
                          {
        std::string html_404;
        FileUtil::ReadFile(html_404,"wwwroot/404.html");
        resp.set_content(html_404,"text/html; charset=utf-8"); });

    // 默认路由
    svr.set_base_dir("./wwwroot");

    svr.listen("0.0.0.0", atoi(argv[1]));
    return 0;
}
